use crate::api::stop::stop::ActiveModel;
use crate::app::AppState;
use crate::common::page::{PageList, PaginationParams};
use crate::common::wrap_valid::{WrappedValidQuery, WrappedValidRequestBody};
use crate::entity::prelude::*;
use crate::error::ApiResult;
use crate::oidc::OidcClaims;
use crate::response::ApiResponse;
use axum::extract::State;
use axum::{debug_handler, Router};
use chrono::{NaiveDate, Utc};
use sea_orm::prelude::*;
use sea_orm::*;
use serde::Deserialize;
use validator::Validate;

pub fn create_router() -> Router<AppState> {
    Router::new()
        .route("/", axum::routing::get(query_effective_stops))
        .route("/add", axum::routing::post(create_user))
}

#[derive(Debug, Deserialize, Validate)]
#[serde(rename_all = "camelCase")]
pub struct StopQueryParams {
    stop_name: Option<String>,
    direction: Option<String>,
    #[validate(nested)]
    #[serde(flatten)]
    pagination: PaginationParams,
}

#[derive(Debug, Deserialize, Validate, DeriveIntoActiveModel)]
#[serde(rename_all = "camelCase")]
pub struct CreateUserModel {
    #[validate(length(max = 100, message = "站名长度不能超过100个字符"))]
    stop_name: String,
    #[validate(custom(function = "crate::validation::is_direction"))]
    direction: String,
    #[serde(deserialize_with = "crate::common::serde::deserialize_date")]
    version_date: Date,
}

#[debug_handler]
pub async fn query_effective_stops(State(AppState { db_connection, oidc_client: _ }): State<AppState>,
                                   WrappedValidQuery(StopQueryParams { stop_name, direction, pagination }): WrappedValidQuery<StopQueryParams>,
) -> ApiResult<ApiResponse<PageList<stop::Model>>> {
    let today = Utc::now().date_naive();
    let paginator = StopEntity::find()
        .apply_if(stop_name.as_ref(), |query, stop_name| {
            query.filter(
                Condition::all()
                    .add(stop::Column::StopName.contains(stop_name))
            )
        })
        .apply_if(direction.as_ref(), |query, direction| {
            query.filter(
                Condition::all()
                    .add(stop::Column::Direction.contains(direction))
            )
        })
        .filter(
            sea_orm::Condition::all()
                .add(stop::Column::VersionDate.lte(today))
                .add(stop::Column::ExpirationDate.gte(today))
                .add(stop::Column::Deleted.eq(false))
        )
        .paginate(&db_connection, pagination.page_size);

    let total = paginator.num_items().await?;
    let items = paginator.fetch_page(pagination.page_num - 1).await?;
    let page_result = PageList::from_pagination(pagination, total, items);

    Ok(ApiResponse::message_ok("ok", Some(page_result)))
}

#[debug_handler]
pub async fn create_user(State(AppState { db_connection, oidc_client: _ }): State<AppState>,
                         OidcClaims(claims): OidcClaims,
                         WrappedValidRequestBody(create_model): WrappedValidRequestBody<CreateUserModel>,
) -> ApiResult<ApiResponse<stop::Model>> {
    // if let Some(username) = claims.preferred_username {
    //     tracing::info!("Login User: {username}");
    // }
    // 鉴权
    let mut active_model = create_model.into_active_model();
    active_model.expiration_date = ActiveValue::set(NaiveDate::from_ymd_opt(9999, 12, 31).unwrap());
    active_model.deleted = ActiveValue::set(false);
    let result = active_model.insert(&db_connection).await?;
    Ok(ApiResponse::ok(Some(result)))
}